#!/bin/bash
#
#    am-obthemes: script to save or restore openbox gui configurations
#    Copyright (C) 2015 damo    <damo@bunsenlabs.org>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#
# Save options are for  Conky(s)
#                       Tint2(s)
#                       Openbox theme
#                       GTK theme
#                       Background (uses Nitrogen or feh, depending which
#                                   has the newer saved bg config file)
#                       Alt Menu (dmenu)
#                       Lightdm login gtk greeter
#                       Exit dialog theme
#                       X configs (.bashrc, .Xresources)
#                       Termite config
#                       Exit dialogue
#
#
# A Screenshot is saved (Windows are hidden briefly so the image
#                        is the bare desktop, with any Tint2s
#                        or Conkys which are running, and a representive
#                        menu and window open)
#
# A time-stamped backup of rc.xml is saved "just in case".
#
# USER VARIABLE: xdotool is used to move the mouse pointer, and assumes the
# root-menu is shown with "Super + Space" keys, and the right mouse button is
# set for "r-click". If you have set these to something else, then edit the
# "MENUMODIFIER" and "MOUSECMD" variables.
# Set the variable "KEYDOWN" to where "Preferences" is in the root-menu (or
# anything else you might want displayed).
# The image viewer is set to be "am-image-viewer". Edit the "IMGCMD" variable
# to change this.
#
# WARNING: It is assumed that the conkys are not being run via a script, so
# they will appear on all desktops. If you usually use a script, then you
# may have to make your own arrangements! Conkys in non-default directories
# can be saved, but will not be seen when running the bl conky chooser
#
########################################################################
#
# KNOWN ISSUES:
# Virtualbox does not allow the guest to move the host mouse cursor, using xdotool,
# so the screenshot may produce an incorrect theme displayed and/or poor positioning.
# A workaround is to move the cursor to some free space, and use the "Enter" key in the
# "Configurations to be saved:" dialog.

HELP='am-obthemes a script to save or restore openbox gui configurations
Options:
    -h --help   show this message

No other options are supported.

 Save options are for  Conky(s)
                       Tint2(s)
                       Openbox theme
                       GTK theme
                       Background (uses Nitrogen or feh, depending which
                                   has the newer saved bg config file)
                       Alt Menu (dmenu)
                       Lightdm login gtk greeter
                       Exit dialog theme
                       X configs (.bashrc, .Xresources)
                       Termite config

 Paths are assumed to be ArcoLinux defaults.

 A Screenshot is saved (Windows are hidden briefly so the image
                        is the bare desktop, with any Tint2s
                        or Conkys which are running, and a representive
                        menu and window open.)

 A time-stamped backup of rc.xml is saved "just in case".

Configuration:

 USER VARIABLE: xdotool is used to move the mouse pointer, and assumes the
 root-menu is shown with "Super + Space" keys, and the right mouse button is
 set for "r-click". If you have set these to something else, then edit the
 "MENUMODIFIER" and "MOUSECMD" variables.
 Set the variable "KEYDOWN" to where "Preferences" is in the root-menu (or
 anything else you might want displayed).
 The image viewer is set to be "am-image-viewer". Edit the "IMGCMD" variable
 to change this.

WARNING: It is assumed that the conkys are not being run via a script, so
 they will appear on all desktops. If you usually use a script, then you
 may have to make your own arrangements! Conkys in non-default directories
 can be saved, but will not be seen when running the bl conky chooser.

KNOWN ISSUES:
 Virtualbox does not allow the guest to move the host mouse cursor, using xdotool,
 so the screenshot may produce an incorrect theme displayed and/or poor positioning.
 A workaround is to move the cursor to some free space, and use the "Enter" key in the
 "Configurations to be saved:" dialog.
'
# look for a help option somewhere
for i in "$@"
do
    case "$i" in
    -h|--help)
        echo "$HELP"
        exit 0
        ;;
    esac
done

#### VARIABLES #########################################################
CONFIGPATH="$HOME/.config/alob"
SETTINGS=""
OBPATH="$HOME/.config/openbox"
CURSESSION="$CONFIGPATH/current"
CONFIGDIR=""
LISTMSG=""
CZEN=0
TZEN=0
NUMDIRS=0
CONKYCMD=""
COLS=0
### CONFIGS VARIABLES
EXITFILE="$HOME/.config/am-exit/am-exitrc"
TERMDIR="$HOME/.config/termite"
TERMFILE="$TERMDIR/config"
FEHFILE="$HOME/.fehbg"
NITRODIR="$HOME/.config/nitrogen"
NITROFILE="$NITRODIR/bg-saved.cfg"
CONKYPATH="$HOME/.config/conky"
CONKYSESSION="$CONKYPATH/conky-sessionfile"
TINTSESSION="$HOME/.config/tint2/tint2-sessionfile"
GTK2=".gtkrc-2.0"
GTK2MINE=".gtkrc-2.0.mine"
GTK3="$HOME/.config/gtk-3.0"
GTK3x="$HOME/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-notifyd.xml"
LDMDIR="/etc/lightdm"
LDM="lightdm-gtk-greeter.conf"
DMENUDIR="$HOME/.config/dmenu"
DMENU="dmenu-bind.sh"
XFILE=".Xresources"
BASHFILE=".bashrc"
PICKOB="OB theme"
PICKGTK="GTK theme"
PICKCONKY="Conky"
PICKTINT="Tint2"
PICKBG="Background Wallpaper"
PICKDMENU="dmenu (Alt menu)"
PICKLDM="Lightdm Login theme"
PICKEXIT="Exit dialog theme"
PICKTERM="Termite"
PICKX="X configs"
### END CONFIGS VARIABLES

### DIALOG VARIABLES
DIALOG="yad --center --undecorated --borders=20 --window-icon=distributor-logo-arcolinux"
DIALOGDEC="yad --center  --borders=20 --window-icon=distributor-logo-arcolinux"
TITLE="ALOB Configuration Manager"
T="--text="
OK="--button=yad-ok:0"
CANCEL="--button=yad-cancel:1"
EXIT="--button=yad-quit:1"
CLOSE="--button=yad-close:1"
TXTINTRO='<big><b>ArcoLinux Openbox Configuration Manager</b></big>


<b>Save or Restore settings for:</b>

    Openbox theme
    GTK theme
    Conkys
    Tint2
    Desktop Background
    Alt Menu (dmenu)
    LightDM theme
    Exit dialog theme
    X configs (.bashrc, .Xresources)
    Termite (if default term)
    + Screenshot'
### END DIALOG VARIABLES

### USER SETTINGS
IMGCMD="gpicview"    # application command to view screenshot
MENUMODIFIER="super+space"  # keybind for show root-menu
MOUSECMD="click 3"          # mouse r-click
KEYDOWN=13           # adjust this for where "Preferences" is in the menu
#### END VARIABLES #####################################################

### FUNCTIONS ##########################################################

function Intro(){
    local INTRO RET
    getSet
    #  If alob/ is empty, then don't display "View Saved" option in Intro dialog
    if (( NUMDIRS > 0 ));then
        INTRO=$($DIALOGDEC "$T$TXTINTRO" \
        --title="$TITLE" \
        --button="Save Settings:0" --button="View Saved:2" $CLOSE \
        --borders=30 \
        2>/dev/null )
    else
        INTRO=$($DIALOGDEC \
        --title="$TITLE" \
        "$T$TXTINTRO" \
        --button="Save Settings:0" --button="yad-close:1" \
        --borders=30 \
        2>/dev/null )
    fi
    RET=$?
    case $RET in
        0)  setName
            saveSettings
            getScrot
            if [[ -d $CONFIGDIR-BKP ]];then
                rm -rf "$CONFIGDIR-BKP"
                echo -e "\n  Temporary $CONFIGDIR deleted\n"
            fi
            restoreSettings
            ;;
        1)  echo "CANCELLED..."
            exit 0
            ;;
        2)  getSet
            restoreSettings
            ;;
        *)  echo "RETURN ERROR" 2>&1
            ;;
    esac
}

function getSet(){      # get name of currently set ALOB config
    NUMDIRS=0
    NUMDIRS=$(ls -l "$CONFIGPATH" | grep -c ^d) # check if any dirs present
    if (( NUMDIRS == 0 ));then
        if [[ -f $CURSESSION ]];then
            rm "$CURSESSION"
        fi
    elif (( NUMDIRS > 0 )) && [[ -f $CURSESSION ]];then
        SET=$(cat "$CURSESSION")
    fi
}

function getActiveMonitorDimensions(){   # Set width and height for View dialog
    declare -a dim=()
    dim=($(am-xinerama-prop))
    W=$(( ${dim[0]} / 3 ))
    H=$(( ${dim[1]} / 3 * 2 ))
    [[ $W =~ ^[0-9]+$ ]] && [[ $H =~ ^[0-9]+$ ]] || {
        print 'Error in getActiveMonitorDimensions'
        exit 1
    }
}

function setName(){  # set name of collection, make dir and session settings file
    MSG="  Configurations will be saved to a new directory in  \
    \n  $CONFIGPATH\n\n  Enter name of new collection...  "
    MSG2="  No file specified for new saved session.\n\n  Try again?"
    LOOP=1
    DEL=0
    while [[ $LOOP ]];do  # loop dialog if nothing is selected
        ANS=$($DIALOG --entry \
            $CANCEL --button="OK:0" \
            "$T$MSG" \
            2>/dev/null )
        if (( $? == 1 )) ;then # Cancel was selected
            Intro
        elif [[ ! $ANS ]] ;then     # entry was empty
            $DIALOG --image="dialog-question" \
            "$CANCEL" "$OK" \
            "$T$MSG2" \
            2>/dev/null
            RET=$?
            echo -e "\n  No name entered for new collection!" 2>&1
            if (( RET == 0 ));then
                continue
            else
                Intro
            fi
        else
            ANS=$(echo $ANS | sed -e 's/ /_/g')    # replace any spaces in dir name
            CONFIGDIR="$CONFIGPATH/$ANS"
            if [[ -d $CONFIGDIR ]];then
                echo -e "\n  $CONFIGDIR already exists"

                $DIALOG --form --image="dialog-question" \
                --text="Overwrite existing saved session?" \
                "$CANCEL" "$OK" \
                --width=300 \
                2>/dev/null

                if (( $? == 0 ));then
                    mv "$CONFIGDIR" "$CONFIGDIR-BKP" && mkdir -p "$CONFIGDIR"
                    DEL=1
                    SETTINGS="$CONFIGDIR/settings.cfg"
                    > "$SETTINGS"
                    LISTMSG="$CONFIGDIR/LISTMSG.txt"
                    > "$LISTMSG"
                    break
                else
                    continue
                fi
            fi
            mkdir -p "$CONFIGDIR"
            SETTINGS="$CONFIGDIR/settings.cfg"
            LISTMSG="$CONFIGDIR/LISTMSG.txt"
            > "$SETTINGS"
            > "$LISTMSG"
            break
        fi
    done
    setText
}

function setText(){
    TIME=$(date)
    if (( DEL == 1 ));then
        TXT="  (Existing session overwritten)"
    else
        TXT=""
    fi
    echo -e "\n  Configuration will be saved as: $ANS$TXT"
    if [[ $1 = repeat ]];then
        > "$LISTMSG"    # reset LISTMSG.txt
    fi
    # Store list in listfile
    echo -e "<b>Configuration name: $ANS</b>\t$TXT\nSaved at $TIME\n" >> "$LISTMSG"
}

function getBg(){    # find if feh or nitrogen was used. Save config file(s)
    if [[ -e $NITROFILE ]] && [[ -e $FEHFILE ]];then  # see which was last used to set background
        if [[ $NITROFILE -nt $FEHFILE ]];then # use most recent method
            BGSET="NITROGEN"
        else
            BGSET="FEH"
        fi
    elif [[ -e $FEHFILE ]] && [[ ! -e $NITROFILE ]];then  # use feh for background
        BGSET="FEH"
    elif [[ -e $NITROFILE ]] &&  [[ ! -e $FEHFILE ]];then    # use nitrogen for background
        BGSET="NITROGEN"
    else
        echo -e "\n  No background-setting application found" 2>&1
        BGSET="None"
    fi
    echo -e "\n  Background to be set with $BGSET"
    case "$BGSET" in
        FEH     )   echo "[BACKGROUND] $BGSET" >> "$SETTINGS"
                    cp "$FEHFILE" "$CONFIGDIR"
                    echo -e "\n  $FEHFILE copied"
                    bgFeh
                    ;;
        NITROGEN)   echo "[BACKGROUND] $BGSET" >> "$SETTINGS"
                    cp "$NITRODIR/nitrogen.cfg" "$CONFIGDIR"
                    cp "$NITROFILE" "$CONFIGDIR"
                    echo -e "\n  Saved Nitrogen file: $NITROFILE"
                    getNitrogen
                    ;;
        None    )   echo -e "\n  No background-setting application found" 2>&1
                    echo "[BACKGROUND] $BGSET" >> "$SETTINGS"
                    ;;
        *       )   echo -e "\n  ERROR: No background config found" 2>&1
                    exit 1
                    ;;
    esac
}

function bgFeh(){    # get Feh saved backgrounds
    FFILE="$CONFIGDIR/.fehbg"
    if [[ -f $FFILE ]];then
        BG=""
        # get fields between single quotes
        for F in $(grep -o "'.*'" $FFILE | sed "s/'//g" 2>/dev/null);do
            BG="$BG$F;\n\t"
        done
        echo -e "\n  Backgrounds set with Feh, using:\n\
        \t$FEHFILE\n\t$BG"
        echo "Background set with feh:\n\t$BG" >> "$LISTMSG"
    else
        echo -e "\n  $FFILE not found" 2>&1
    fi
}

function getNitrogen(){  # get Nitrogen saved backgrounds
    NFILE="$CONFIGDIR/bg-saved.cfg"
    if [[ -f $NFILE ]];then
        BG=""
        while read line;do
            BGLINE=$(echo $line | awk -F"file=" '{print $2}')
            if [[ $BGLINE ]];then
                BG="$BG$BGLINE;\n"
            fi
        done < "$NFILE"
        echo -e "\n  Backgrounds set with Nitrogen, using:\t$NITROFILE"
        echo -e "$BG"
        echo "Background set with nitrogen:\n$BG" >> "$LISTMSG"
    else
        echo -e "\n  $NFILE not found" 2>&1
    fi
}

function getConky(){
    CONKYCMD=""
    LISTMSGTXT=""
    TXT=""
    CONKYTEMP=$(mktemp --tmpdir alob.XXXX)
    if [[ $(pidof conky) ]];then    # get full command of running conkys
        > "$CONKYTEMP"
        pgrep -a conky | while read pid CMD;do
            echo "$CMD;" >> "$CONKYTEMP"
        done
        TXT="Conkys:\n\n"
        DEF="Default"
        MSG="Running Conkys:"
        while read line;do
            LINE=$(echo "$line" | sed 's/;//')
            CONKYCMD="$CONKYCMD $LINE & sleep 1s;"
            if [[ $LINE = "conky" ]] || [[ $LINE = "conky -q" ]];then
                line="$DEF"
            else
                line=${line##*" "}      # get full filepath
            fi
            TXT="$TXT$line"
            LISTMSGTXT="$LISTMSGTXT\n\t$line"
        done < "$CONKYTEMP"
        echo "[CONKY] $CONKYCMD" >> "$SETTINGS"
        rm -f "$CONKYTEMP"
        echo "$MSG\t$LISTMSGTXT\n" >> "$LISTMSG"
        echo -e "\n  Saved running Conky(s)"
    else
        DLG=$($DIALOG --form --image="dialog-warning" \
        --text="You selected to save Conkys\nbut none are running" \
        "$OK" \
        --width=300) 2>/dev/null
    fi
}

function checkConkyzen(){    # see if am-conkyzen and session file present
    if type am-conkyzen &>/dev/null;then
        if [[ -f $CONKYSESSION ]]; then
            CZEN=1  # set flag for Restore choice
        fi
    fi
}

function getTint(){
    TEMPTINT=$(mktemp --tmpdir alob.XXXX) # make blank tempfile, to save running tint2 paths
    if [[ $(pidof tint2) ]];then
        pgrep -a tint2 | while read pid cmd;do
            if [[ ${cmd%% *} = tint2 ]];then
                TPATH=$(echo "$cmd" | awk '{print $NF}')
                echo "$TPATH;" >> "$TEMPTINT"
            fi
        done
        TXT="Tint2s:\n\n"
        MSG="Running Tint2s:"
        TINTCMD=""
        LISTMSGTXT=""
        while read line;do
            TXT="$TXT$line"
            LINE=$(echo "$line" | sed 's/;//')
            if [[ $LINE = tint2 ]];then         # default command was used
                TINTCMD="$TINTCMD$LINE;"
                LISTMSGTXT="$LISTMSGTXT\n\tDefault Tint2"
            else
                TINTCMD="$TINTCMD$LINE;"
                LISTMSGTXT="$LISTMSGTXT\n\t$LINE"
            fi
        done < "$TEMPTINT"
        echo "[TINT2] $TINTCMD" >> "$SETTINGS"
        rm -f "$TEMPTINT"
        echo "$MSG\t$LISTMSGTXT\n" >> "$LISTMSG"
        echo -e "\n  Saved running Tint2(s)"
    else
        DLG=$($DIALOG --form --image="dialog-warning" \
        --text="You selected to save Tint2\nbut none are running" \
        "$OK" \
        --width=300) 2>/dev/null
    fi
}

function killTints(){
    pgrep -a tint2 | while read pid cmd; do
        if [[ ${cmd%% *} = tint2 ]]; then
            kill "$pid"
        fi
    done
}

function checkTint2zen(){    # see if am-tint2zen and session file present
    if type am-tint2zen &>/dev/null;then
        if [[ -f $TINTSESSION ]]; then
            TZEN=1          # set flag for Restore choice
        fi
    fi
}

function getOBtheme(){   # copy <theme> section from rc.xml to obtheme.txt
    RCFILE="$OBPATH/rc.xml"
    tag="theme"
    sed -n "/<$tag>/,/<\/$tag>/p" "$RCFILE" > "$CONFIGDIR/obtheme.txt"
    echo "[OBTHEME]" >> "$SETTINGS"
    getOBname
}

function getOBname(){    # get OB theme name
    OBFILE="$CONFIGDIR/obtheme.txt"
    OBTHEME=$(awk 'NR==2 {print;exit}' $OBFILE | awk -F'[>|<]' '{print $3}')
    TXT="Openbox theme:  $OBTHEME\n"
    echo -e "\n  Saved $TXT"
    echo "$TXT" >> "$LISTMSG"
}

function getGTKtheme(){
    GTKTHEMES=( "$HOME/$GTK2" "$HOME/$GTK2MINE" "$GTK3" "$GTK3x" )
    for f in "${GTKTHEMES[@]}";do
        if [[ -f $f ]];then
            cp "$f" "$CONFIGDIR"
        elif [[ -d $f ]];then
            cp -r "$f" "$CONFIGDIR"
        fi
    done
    echo "[GTK]" >> "$SETTINGS"
    getGTKname
}

function getGTKname(){   # get GTK theme name
    GTKFILE="$CONFIGDIR/.gtkrc-2.0"
    while read line;do
        if [[ $(echo $line | grep "gtk-theme-name" ) ]] &>/dev/null;then
            GTKTHEME=$(echo $line | awk -F '"' '{print $2}')
        fi
    done < "$GTKFILE"
    TXT="GTK theme:  $GTKTHEME\n"
    echo -e "\n  Saved $TXT"
    echo "$TXT" >> "$LISTMSG"
}

function getDmenu(){
    if [[ -d $DMENUDIR ]];then
        cp "$DMENUDIR/$DMENU" "$CONFIGDIR"
        echo "[DMENU]" >> "$SETTINGS"
        TXT="dmenu config:  $DMENUDIR/$DMENU\n"
        echo -e "\n  Saved $TXT"
        echo "$TXT" >> "$LISTMSG"
    else
        echo "  $DMENUDIR/$DMENU not found"
    fi
}

function getLightdm(){
    if [[ -f $LDMDIR/$LDM ]];then
        cp "$LDMDIR/$LDM" "$CONFIGDIR"
        TXT="Lightdm config:  $LDMDIR/$LDM\n"
        echo -e "\n  Saved $TXT"
        echo "[LIGHTDM]" >> "$SETTINGS"
        echo "$TXT" >> "$LISTMSG"
    fi
}

function getTermite(){
    if [[ -e $TERMFILE ]];then
        cp "$TERMFILE" "$CONFIGDIR"
        TXT="Termite config:  $TERMFILE\n"
        echo -e "\n  Saved $TXT"
        echo "[Termite]" >> "$SETTINGS"
        echo "$TXT" >> "$LISTMSG"
    fi
}

function getXconfig(){
    XFILE="$HOME/.Xresources"
    BASHFILE="$HOME/.bashrc"
    if [[ -f $XFILE ]];then
        cp "$XFILE" "$CONFIGDIR"
    fi
    if [[ -f $BASHFILE ]];then
        cp "$BASHFILE" "$CONFIGDIR"
    fi
    TXT="X terminal config:  $BASHFILE;$XFILE\n"
    echo -e "\n  Saved $TXT"
    echo "[XFILES]" >> "$SETTINGS"
    echo "$TXT" >> "$LISTMSG"
}

function getBLexitrc(){
    if [[ -f $EXITFILE ]];then
        cp "$EXITFILE" "$CONFIGDIR"
        echo "[EXITRC]" >> "$SETTINGS"
        TXT="am-exitrc config:  $EXITFILE\n"
        echo -e "\n  Saved $TXT"
        echo "$TXT" >> "$LISTMSG"
    else
        echo "  $EXITFILE not found"
    fi
}

function checkTint2(){   # kill or restart tint2s for screenshot, if necessary
    if [[ $1 = stop ]];then
        if ! cat "$SETTINGS" | grep "TINT2" &>/dev/null;then
            tmpTINT=$(mktemp --tmpdir alob.XXXX) # make blank tempfile, to save running tint2 paths
            if [[ $(pidof tint2) ]];then
                pgrep -a tint2 | while read pid cmd;do
                    if [[ ${cmd%% *} = tint2 ]];then
                        echo $cmd >> "$tmpTINT"
                    fi
                done
            fi
            killTints
        fi
    fi
    if [[ $1 = start ]];then
        if [[ -f "$tmpTINT" ]] 2>/dev/null;then
            while read line;do
                ($line &) &>/dev/null
                sleep 1s
            done < "$tmpTINT"
            rm -f "$tmpTINT"
        fi
    fi
}

function getScrot(){
    pid=""
    TMPSCROT=$(mktemp --tmpdir alob.XXXX)
    SCROT="$CONFIGPATH/$ANS"
    CURRDTOP=$(xprop -root _NET_CURRENT_DESKTOP | tail -c -2) # desktop number
    MONS=$(xrandr -q | grep -c " connected")    # number of monitors
    # Set mouse position, for appearance of root-menu
    screenW=$(xrandr -q | awk '/Screen/ {print $8}')
    screenH=$(xrandr -q | awk '/Screen/ {print $10}')
    screenH=${screenH%,}

    if (( MONS == 1 ));then # single monitor
        appX=$(( (screenW/20)*8 ))
        menuX=$(( (screenW/20)*2 ))
    else
        appX=$(( (screenW/20)*4 ))
        menuX=$(( (screenW/20)*1 ))
    fi
    appY=$(( (screenH/20)*4 ))
    menuY=$(( (screenH/20)*4 ))

    wmctrl -l -x > "$TMPSCROT"      # store window list in tempfile
    wmctrl -k on                    # hide windows, show desktop
    # show any conkys which have been hidden by wmctrl, (ie not own_window_type desktop);
    # unless Conkys weren't selected to be saved
    if cat "$SETTINGS" | grep "CONKY" &>/dev/null;then
        for CONK in $(xdotool search --classname "Conky");do
            xdotool windowactivate "$CONK" 2>/dev/null
        done
    fi
    checkTint2 stop     # stop running Tint2s for the scrot,
                        # if not selected to be saved
    # start lxappearance
    lxappearance &
    pid=$!
    sleep 0.5
    # get lx window, make sure it loses focus, then move mouse and start root-menu
    LX=$(xdotool getwindowfocus)
    xdotool windowmove --sync $LX $appX $appY && sleep 0.1 && \
    xdotool mousemove --sync --window $LX -- -50 0 && xdotool click 1
    xdotool mousemove --sync $menuX $menuY && xdotool key --clearmodifiers $MENUMODIFIER

    i=1
    while (( i <= KEYDOWN ));do
        xdotool key --delay 50 Down
        i=$(( i+1 ))
    done
    xdotool key --delay 20 Right && sleep 0.3

    # take scrot
    scrot -t 9 "$SCROT.jpg"    # scrot thumbnail @9% fullsize
    THUMB=$(find "$CONFIGPATH" -maxdepth 1 -type f -name "*-thumb.jpg" 2>/dev/null)
    mv "$THUMB" "$CONFIGDIR"

    # close root menu
    xdotool mousemove_relative --sync --polar 0 10 $MOUSECMD
    # kill lxappearance
    if [[ $(pgrep lxappearance | grep $pid) ]];then
        kill -9 $pid &>/dev/null
    fi

    # restore hidden windows
    while read line; do
        WINDOW=$(echo $line | awk '{print $1}') # Window_ID is first field
        DTOP=$(echo $line | awk '{print $2}' )  # Desktop number is second field
        if (( DTOP == CURRDTOP )) &>/dev/null;then
            xdotool windowactivate "$WINDOW"
        fi
    done < "$TMPSCROT"
    # restore any hidden Conkys
    for CONK in $(xdotool search --classname "Conky");do
        xdotool windowactivate "$CONK" 2>/dev/null
    done
    checkTint2 start        # restore any stopped Tint2s
    rm -f "$TMPSCROT"
}

function restoreGTK(){   # $1 is chosen saved config dir
    GTKPATHS=( "$HOME" "$HOME" "$GTK3" "$GTK3x" )
    GTKSAVED=( "$1/$GTK2" "$1/$GTK2MINE" "$1/gtk-3.0" "$1/xfce4-notifyd.xml" )
    i=0
    for f in ${GTKSAVED[@]};do
        if [[ -e $f ]];then     # if destination exists
            if [[ -e ${GTKPATHS[i]} ]];then
                if [[ ${GTKSAVED[i]} = $1/gtk-3.0 ]];then
                    cp -r ${GTKSAVED[i]}/* ${GTKPATHS[i]} # restore contents of gtk-3.0
                fi
                cp ${GTKSAVED[i]} ${GTKPATHS[i]}
                echo -e "\n  Restored: ${GTKSAVED[i]}"
            else
                echo -e "\n  Restore path ${GTKPATHS[i]} not found" 2>&1
            fi
        else
            echo -e "\n  ${GTKSAVED[i]} not found" 2>&1
        fi
        i=$((i+1))
    done
}

function restoreOBrc(){
    RCFILE="$OBPATH/rc.xml"
    THEMEFILE="$1/obtheme.txt"
    FTEMP=$(mktemp --tmpdir alob.XXXX)
    if [[ $(grep "[OBTHEME]" "$1/settings.cfg" ) ]] &>/dev/null;then
        # backup rc.xml first
        NOW=$(date +"%Y%m%d-%H%M%S")
        RCBKP="$RCFILE.alob.$NOW"
        cp "$RCFILE" "$RCBKP"
        # remove older backups
        for f in $(find "$OBPATH" -type f|grep .alob. );do
            if [[ $f -ot $RCBKP ]];then
                rm "$f"
            fi
        done
        ## put placeholder in place of <theme> section, write to tempfile
        sed -n "/<theme>/{:a;N;/<\/theme>/!ba;N;s/.*\n/THEMESECTION\n/};p" "$RCFILE" > "$FTEMP"
        # replace placeholder from theme file
        sed -i "/THEMESECTION/{
            s/THEMESECTION//g
            r $THEMEFILE
        }" "$FTEMP"
        sed -i '/^$/d' "$FTEMP"   # remove empty lines
        cp "$FTEMP" "$RCFILE"     # overwrite rc.xml
        echo -e "\n  rc.xml backed up and edited for OB theme"
        rm -f "$FTEMP"
    fi
}

function restoreTint2(){      # write to tint2 session file
    echo "$1" | awk -F';' '{for(i=1; i<=NF; i++) print $i}' >> "$TINTSESSION"
    killTints
    while read tintline;do
        (tint2 -c "$tintline" &) &>/dev/null
        sleep 1s
    done < "$TINTSESSION"
}

function restoreDmenu(){
    DFILE="$1"
    if [[ -e $DMENUDIR ]];then        # backup DMENU first
        DMENUBKP="$DMENUDIR/$DMENU.bkp"
        cp "$DMENUDIR/$DMENU" "$DMENUBKP"
        cp "$DFILE" "$DMENUDIR"
        echo -e "\n  $DMENUDIR/$DMENU backed up and restored"
    else
        cp "$DFILE" "$DMENUDIR/$DMENU"
        echo -e "\n  $DMENUDIR/$DMENU restored"
    fi
}

function restoreBLexitrc(){
    EFILE="$1"
    if [[ -e $EXITFILE ]];then        # backup am-exitrc first
        EFILEBKP="$EFILE.bkp"
        cp "$EFILE" "$EFILEBKP"
        cp "$EFILE" "$EXITFILE"
        echo -e "\n  $EXITFILE backed up and restored"
    else
        cp "$EFILE" "$EXITFILE"
        echo -e "\n  $EXITFILE restored"
    fi
}

function restoreLightdm(){   # need sudo to restore lightdm-gtk-greeter.conf
    CMD="cp $1 $LDMDIR/$LDM"
    TXT="Authenticate restore of lightdm-gtk-greeter.conf"
    LOOP=1
    while [[ $LOOP ]];do
        gksudo -m "$TXT" "$CMD"
        DLG=$?
        case "$DLG" in
            0   )   MSG="  Restored: lightdm-gtk-greeter.conf"
                    echo -e "\n  $MSG"
                    break
                    ;;
            255 )   MSG="  Authentication cancelled\n\nlightdm-gtk-greeter.conf was not restored"
                    echo -e "\n  $MSG" 2>&1
                    break
                    ;;
            *   )   MSG="  Password input failed\n\nlightdm-gtk-greeter.conf was not restored"
                    echo -e "\n  $MSG" 2>&1
                    "$DIALOG" --image="dialog-warning" "$T$MSG" "$OK" 2>/dev/null
                    ;;
        esac
    done
}

function restoreXsettings(){
    XBKP=""
    for var in "$@";do
        if [[ -e $var ]];then        # backup .bashrc & .Xresources first
            XBKP="$var.bkp"
            cp "$var" "$XBKP"
            cp "$var" "$HOME"
            echo -e "\n  $var backed up and restored"
        else
            cp "$var" "$HOME"
            echo -e "\n  $var restored"
        fi
    done
}

function restoreTermite(){
    TFILE="$1"
    if [[ -e $TERMDIR ]];then        # backup Termite/config first
        TERMBKP="$TERMDIR/config.bkp"
        cp "$TFILE" "$TERMBKP"
        cp "$TFILE" "$TERMDIR/config"
        echo -e "\n  $TERMDIR/config backed up and restored"
    else
        cp "$TFILE" "$TERMDIR/config"
        echo -e "\n  $TERMDIR/config restored"
    fi
}

function reloadGTK(){ # reload gtk theme after restoring saved config
python - <<END
import gtk

events=gtk.gdk.Event(gtk.gdk.CLIENT_EVENT)
data=gtk.gdk.atom_intern("_GTK_READ_RCFILES", False)
events.data_format=8
events.send_event=True
events.message_type=data
events.send_clientmessage_toall()

END
}

function cleanup(){
    if [[ $1 = all ]];then
        if [[ -d $CONFIGDIR ]];then
            rm -rf "$CONFIGDIR"
            echo -e "\n  Deleted $CONFIGDIR"
        fi
        if [[ -d $CONFIGDIR-BKP ]];then
            mv "$CONFIGDIR-BKP" "$CONFIGDIR"
            echo -e "\n  Cancelled\n..Temporary $CONFIGDIR restored\n"
        fi
        rm -f /tmp/alob.*
    elif [[ $1 = save ]];then
        saveSettings
    fi
}

function saveSettings(){
    SHOW=0
    if (( COLS == 0 ));then
        SELECT="FALSE"
    else
        SELECT="TRUE"
    fi
    COLUMNS=(\
        $SELECT "$PICKOB" \
        $SELECT "$PICKGTK" \
        $SELECT "$PICKCONKY" \
        $SELECT "$PICKTINT" \
        $SELECT "$PICKBG" \
        $SELECT "$PICKDMENU" \
        $SELECT "$PICKLDM" \
        $SELECT "$PICKEXIT" \
        $SELECT "$PICKX" \
        )
    # add Termite to array if set as default
    if  readlink -f /usr/bin/x-terminal-emulator | grep Termite &>/dev/null;then
        COLUMNS=("${COLUMNS[@]}" $SELECT "$PICKTERM")
    fi

    SLOOP=1
    while (( SLOOP == 1 ));do
        CHOICE=$($DIALOGDEC --list --checklist \
            --title="Choose the configs to save..." \
            --button="Select All:2" \
            $CANCEL $OK \
            --height=340 \
            --column="Select" --column="Config" "${COLUMNS[@]}" \
            2>/dev/null )
            ret=$?
        if (( ret == 1 )); then # cancel button pressed
            COLS=0
            cleanup all
            restoreSettings
        elif (( ret == 2 ));then
            COLS=1
            saveSettings
            SHOW=1
        else
            if [[ ! $CHOICE ]] ; then # entry field is empty, so try again
                RET=$($DIALOG  --image="dialog-question" \
                --text="\n  Make a selection...." \
                $EXIT $OK \
                --width=300 \
                2>/dev/null )
                if (( $? == 1 ));then
                    cleanup all
                fi
            else
                i=0
                retChoice=()
                OIFS=$IFS # save Internal Field Separator
                IFS=$"|" # separator is "|" in returned choices
                # dialog return is in format 'TRUE|value|\nTRUE|value'
                for ret in $CHOICE; do
                    if [[ $(echo $ret | grep TRUE) ]] &>/dev/null;then
                        continue
                    fi
                    retChoice[$i]="$ret"
                    i=$((i+1))
                done
                IFS=$OIFS # reset IFS back to default
                len=${#retChoice[@]}
                for (( i=0; i<${len}; i++ ));do
                    item="${retChoice[$i-1]}"
                    case "$item" in
                        "$PICKOB"   )   getOBtheme
                                        ;;
                        "$PICKGTK"  )   getGTKtheme
                                        ;;
                        "$PICKCONKY")   getConky
                                        ;;
                        "$PICKTINT" )   getTint
                                        ;;
                        "$PICKBG"   )   getBg
                                        ;;
                        "$PICKDMENU")   getDmenu
                                        ;;
                        "$PICKLDM"  )   getLightdm
                                        ;;
                        "$PICKEXIT" )   getBLexitrc
                                        ;;
                        "$PICKTERM" )   getTermite
                                        ;;
                        "$PICKX"    )   getXconfig
                                        ;;
                        *           )   echo -e "\n  Unknown value!" 2>&1
                                        exit 1
                                        ;;
                    esac
                done
                SLOOP=0
            fi
        fi
    done
    if (( SHOW == 0 ));then
        COLS=0      # reset columns unselected
        TXT="<big><b><u>Openbox Configurations to be saved:</u></b></big>\n\n"
        TXT2=$(cat "$LISTMSG")
        NEW=$($DIALOG --text="$TXT$TXT2") 2>/dev/null
        ret=$?
        if (( ret == 1 ));then
            cleanup all
            restoreSettings
        else
            echo "$ANS" > "$CURSESSION"     # replace entry in saved config flag file
        fi
    fi
}

function ViewRestoreDialog(){  #   Display saved theme collections
    getSet          # get name of latest set alob config
    if (( NUMDIRS == 0 ));then   # no saved configs; go back to Intro dialog
        Intro
    fi
    DLGLIST=""
    setARR=()
    namesARR=()
    thumbsARR=()
    i=0
    for dir in "$CONFIGPATH"/* ;do
        if [[ -d $dir ]];then
            if [[ -e $dir/settings.cfg ]];then
                d=$(echo $dir | sed -e 's/ /_/g')    # replace any spaces in dir name
                namesARR[$i]="<big>$(basename $d)</big>" # add theme collection name to array
                d=${d##*/}  # get directory name
                # Get name of current session, set icon for TRUE/FALSE
                if [[ $SET = $d ]];then
                    setARR[$i]="yad-yes"
                else
                    setARR[$i]="yad-no"
                fi
                IMGTHUMB="None"     # Placeholder if no thumbnail found
                f="$dir"/*"-thumb.jpg"
                if [[ $f ]];then
                    IMGTHUMB="$f"
                fi
                thumbsARR[$i]="$IMGTHUMB"
                CONFIGS="\""
                while read line;do
                    CONFIGS="$CONFIGS $line\n"
                done < "$dir/LISTMSG.txt"
                CONFIGS="$CONFIGS\""
                configARR[$i]="$CONFIGS" # add saved configs to array
            fi
            i=$((i+1))
        fi
    done
    for ((j=0; j<${#namesARR[*]}; j++));do
        DLGLIST="$DLGLIST ${setARR[j]} ${namesARR[j]} ${thumbsARR[j]}"
    done
}

function restoreSettings(){
    ViewRestoreDialog
    FPATH=""
    LOOP=1
    while [[ $LOOP ]] ;do
        CONFIG=$($DIALOGDEC --list --title="$TITLE" \
            --text="Double-click selection, or \"Enter\", or use the \"Restore\" button to restore settings\n" \
            --separator=" " \
            --button="About:5" \
            --button="View image:4" --button="Add New:3" \
            --button="Delete:2" --button="Restore:0" --button="yad-quit:1" \
            --always-print-result \
            --width=$W --height=$H --center --image-preview \
            --expand-column=3 \
            --column="Last Set:IMG" \
            --column="Config Name":TEXT \
            --column="Screenshot":IMG \
            $DLGLIST \
            2>/dev/null )
        RET=$?
        if [[ $CONFIG ]];then
            DIR=$(echo "$CONFIG" | awk -F'[>|<]' '{print $3}' )
            FPATH="$CONFIGPATH/$DIR"
        fi
        case $RET in
            0)  SAVED="$FPATH/LISTMSG.txt"
                TEXT="Restoring Configs saved as <big>$DIR</big>\n\n"
                TEXT="$TEXT$(cat $SAVED)"
                $DIALOG "$T$TEXT" "$CANCEL" "$OK" 2>/dev/null
                if (( $? == 0 ));then
                    echo $(basename $FPATH) > "$CURSESSION"
                    break
                fi
                ;;
            1)  exit 0
                ;;
            2)  if [[ ! $CONFIG ]];then
                    $DIALOG --text="Make a selection before trying to delete" "$EXIT" "$OK" 2>/dev/null
                    if (( $? == 0 ));then
                        continue
                    else
                        exit 0
                    fi
                fi
                TEXT="Delete saved configurations <b>$FPATH</b>\nand screenshot?"
                $DIALOG "$T$TEXT" "$CANCEL" "$OK" 2>/dev/null

                if (( $? == 0 ));then
                    rm -rf "$FPATH"
                    rm "$FPATH.jpg"
                    echo -e "\n$DIR DELETED"
                    currentsession=$(cat $CURSESSION)
                    fpath=$(basename $FPATH)
                    if [[ $currentsession = $fpath ]];then
                        echo "" > "$CURSESSION"
                    fi
                    restoreSettings
                else
                    continue
                fi
                ;;
            3)  setName
                saveSettings
                getScrot
                $DIALOG --text="Settings were saved as <b>$ANS</b>" --image="yad-save" "$OK" 2>/dev/null
                if [[ -d $CONFIGDIR-BKP ]];then
                    rm -rf "$CONFIGDIR-BKP"
                    echo -e "\n  Temporary $CONFIGDIR deleted\n"
                fi
                restoreSettings
                ;;
            4)  # show screenshot in image viewer
                SEL=$(echo "$CONFIG" | awk -F'[>|<]' '{print $3}' )
                if [[ $SEL ]];then
                    img="$CONFIGPATH/$SEL.jpg"
                    $IMGCMD "$img"
                else
                    $DIALOG --text="Make a selection" 2>/dev/null
                fi
                restoreSettings
                ;;
            5)  Intro
                ;;
            *)  if (( RET == 252 ));then
                    echo -e "\n  Exited with \"ESC\" key"
                else
                    echo -e "\n  Error= $RET" 2>&1
                fi
                exit 1
                ;;
        esac
    done
    SETCFG="$FPATH/settings.cfg"
    # Get chosen saved configs and restore them
    # kill conkys and tint2s, in case saved config doesn't include them
    if [[ $(pidof conky) ]];then
        killall conky
    fi
    if [[ $(pidof tint2) ]];then
        killall tint2
    fi
    while read line;do
        TAG=$(echo $line | awk '{print $1}')
        VAL=$(echo $line | awk '{print $2}')
        case "$TAG" in
            "[TINT2]"       )   checkTint2zen # see if am-tint2zen installed
                                if (( TZEN == 1 ));then
                                    > "$TINTSESSION" # overwrite tint2 session file
                                fi
                                TINTCMD=$(echo $line | cut -d ' ' -f2-)
                                restoreTint2 "$TINTCMD"
                                ;;
            "[CONKY]"       )   checkConkyzen # see if am-conkyzen installed
                                if (( CZEN == 1 ));then
                                    > "$CONKYSESSION" # overwrite conky session file
                                fi
                                CONKYCMD=$(echo $line | cut -d ' ' -f2-)
                                # write to conky session file...
                                echo $CONKYCMD | awk -F';' '{for(i=1; i<=NF; i++) print $i}' >> "$CONKYSESSION"
                                killall conky
                                source "$CONKYSESSION"
                                ;;
            "[GTK]"         )   restoreGTK "$FPATH"
                                reloadGTK
                                ;;
            "[OBTHEME]"     )   restoreOBrc "$FPATH"
                                ;;
            "[BACKGROUND]"  )   if [[ $VAL = FEH ]];then
                                    cp "$FPATH/.fehbg" "$HOME"
                                    source "$HOME/.fehbg"
                                else
                                    cp "$FPATH/bg-saved.cfg" "$NITRODIR"
                                    nitrogen --restore
                                fi
                                ;;
            "[DMENU]"       )   restoreDmenu "$FPATH/$DMENU"
                                ;;
            "[LIGHTDM]"     )   restoreLightdm "$FPATH/$LDM"
                                ;;
            "[EXITRC]"      )   restoreBLexitrc "$FPATH/am-exitrc"
                                ;;
            "[XFILES]"      )   restoreXsettings "$FPATH/.bashrc" "$FPATH/.Xresources"
                                ;;
            "[Termite]"  )   restoreTermite "$FPATH/config"
                                ;;
            *               )   echo -e "  Unknown value!" 2>&1
                                restoreSettings
                                ;;
        esac
    done < "$SETCFG"
    openbox --reconfigure
    restoreSettings
}

### END FUNCTIONS ######################################################
# test for alobthemes config directory, create if it doesn't exist
mkdir -p "$CONFIGPATH"
# create file to hold most recent saved configuration name
if [[ ! -f $CURSESSION ]] &>/dev/null;then
    touch "$CURSESSION"
fi
getActiveMonitorDimensions
getSet
if (( NUMDIRS == 0 ));then
    Intro
else
    restoreSettings
fi
exit 0
